# 8. 编程实践

  1. 避免双重求值(使用eval(),Function()构造函数,setTimeout(),setInterval()),每次调用eval()时都要创建一个新的解释器/编译器实例。
  2. 使用Object/Array直接量,对象属性和数组项越多,使用直接量的好处就越明显。
var a={};
vara b=[];
1
2
  1. 避免重复工作

别做无关紧要的工作,别重复做已经完成的工作。

使用addEventListener和attachEvent时每次都要判断。用户不可能在页面加载完成后奇迹般的改变浏览器,那么这次检查就是重复的。如果在第一次调用addHandler()时就确定addEventListener()是存在的,那么随后每次调用时它应该也都存在。每次调用一个函数都重复相同的工作是一种浪费。

# 延迟加载

function addHandler(target,eventType,handler){
  //复写现有函数
  if(target.addEventListener){
    addHandler=function(target,eventType,handler){
      target.addEventListener(eventType,handler,false);
    }
  } else {
    addHandler=function(target,eventType,handler){
      target.attachEvent('on'+eventType,handler);
    }
  }

  //调用新函数
  addHandler(target,eventType,handler);
}

function removeHandler(target,eventType,handler){
  //复写现有函数
  if(target.removeEventListener){
    removeHandler=function(target,eventType,handler){
      target.addEventListener(eventType,handler,false);
    }
  } else {
    removeHandler=function(target,eventType,handler){
      target.detachEvent('on'+eventType,handler);
    }
  }

  //调用新函数
  removeHandler(target,eventType,handler);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

调用延迟加载函数时,第一次总会消耗较长的时间,因为她必须运行检测接着再调用另一个函数完成任务。但随后调用相同的函数会更快,因为不需要再执行检测逻辑。当一个函数在页面中不会立刻调用时,延迟加载是最好的选择。

# 条件预加载

var addHandler=document.body.addEventListener?
    function(target,eventType,handler){
      target.addEventListener(eventType,handler,false);
    }:
    function(target,eventType,handler){
      target.attachEvent('on'+eventType,handler);
    }
1
2
3
4
5
6
7

条件预加载确保所有函数调用消耗的时间相同。其代价是需要在脚本加载时就检测,而不是加载后。预加载适用于一个函数马上就要被用到,并且在整个页面的生命周期中频繁出现的场合。

  1. 位操作过程与js其他数学运算和布尔操作相比要快很多。如果你看到32位数字的二进制底层表示,你会发现偶数的最低位是0,奇数最低位是1.当此数位偶数,那么它和1进行按位与运算的结果是0.
if(i & 1){
  className="odd";//奇数
} else {
  className="even";//偶数
}
1
2
3
4
5
  1. 原生方法 原生的querySelector()和querySelectorAll()方法完成任务平均所需时间是基于js的css查询的10%。当原生方法可用时,尽量使用它们。特别是数学运算和DOM操作。用编译后的代码做越多的事情,你的代码就越快。。Chrome对原生方法和你的代码都使用即时js编译器,所以它们之间的性能差别不大。